package com.pachong.android.frameworkbase.utils;


import android.media.MediaRecorder;
import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;

/**
 *
 * 录音器，有启动、暂停功能。
 *
 * 初始化需要传入录音文件名，录音结束之后会保存录音文件并回收资源，并且将文件名变量设置为null,如果想再次用此recorder录音必须重新给他设置一个文件名
 *
 * @Author: PV
 * @E-mail: pengveivei@sina.cn
 * @CreateDate: 2016-06-20
 * @Version: 1.0.0
 */
public class Recorder {

	private final static String TAG = Recorder.class.getName();

	public enum State {
		IDLE, RECORDING, PAUSE, STOP
	}

	private State mState = State.IDLE;

	/**
	 * 最后输出的文件名，由用户指定
	 */
	private File mDestFile = null;
	private File mTempFile;// 临时录音文件

	private ArrayList<String> mTempFiles;// 缓存录音文件，录音结束后合并输出

	/** 音频文件的格式 */
	public final static String SUFFIX_AAC = ".aac";
	private MediaRecorder mMediaRecorder;


	/**
	 * 前提保证文件路径存在，这里不做路径检查
	 * 
	 * @param fileName
	 */
	public Recorder(String fileName) {
		mDestFile = new File(fileName);
		mTempFiles = new ArrayList<String>();
	}


	/**
	 * 开始录音
	 * @throws IOException 
	 */
	public void start() throws IOException {
		if (mState == State.IDLE) {
			mTempFiles.clear();
			startMediaRecorder();

		} else if (mState == State.PAUSE) {
			startMediaRecorder();

		} else {
			throw new RuntimeException("Recorder start error: 状态异常，当前状态是 " + mState + ", 无法start");
		}
		mState = State.RECORDING;
	}


	/**
	 * 暂停录音
	 * 
	 * 允许在RECORDING状态下操作，其他状态抛出异常
	 */
	public void pause() {
		if (mState == State.RECORDING) {
			stopMediaRecorder();
			mTempFiles.add(mTempFile.getPath());

		} else {
			throw new RuntimeException("Recorder pasue error: 状态异常，当前状态是 " + mState + ", 无法pause");
		}
		mState = State.PAUSE;

	}

	
	/**
	 * 获取录音文件，在stopped的状态下才能获取
	 * @return audio file
	 */
	public File getAudioFile() {
		if(mState == State.STOP) {
			if(mDestFile != null && mDestFile.exists()) {
				return mDestFile;
			} else {
				return null;
			}
			
		} else {
			Log.e(TAG, "当前Recorder所处的state不允许获取录音文件，请检查当前Recorder的状态");
			return null;
		}
	}

	/**
	 * 停止录音
	 * 
	 * 允许在RECORDING状态和PAUSE状态下操作，其他状态抛出异常
	 */
	public void stop() {
		if (mState == State.RECORDING) {
			pause();
			stop();

		} else if (mState == State.PAUSE) {
			try {
				createDestAudio();
				
			} catch (IOException e) {
				Log.e(TAG, "error : 目标音频文件生成失败");
				e.printStackTrace();
				
			} finally {
				recycle();
			}

		} else {
			throw new RuntimeException("Recorder stop error: 状态异常，当前状态是 " + mState + ", 无法stop");
		}

		mState = State.STOP;

	}

	public State state() {
		return mState;
	}

	private void recycle() {
		stopMediaRecorder();
		deleteTempFiles();
		mTempFile = null;
		mTempFiles.clear();
	}


	private void startMediaRecorder() throws IOException {
		String tmpFileName = getRandomFileName();
		Log.i(TAG, "Temp file name == " + tmpFileName);
		// 创建音频文件
		mTempFile = new File(tmpFileName);
		if(!mTempFile.exists()) {
			mTempFile.createNewFile();
		} 
		mMediaRecorder = new MediaRecorder();
		mMediaRecorder.reset();
		// 设置录音为麦克风
		mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
		mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
		mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);

		// 录音文件保存这里
		mMediaRecorder.setOutputFile(mTempFile.getAbsolutePath());
		try {
			mMediaRecorder.prepare();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		mMediaRecorder.start();

	}


	
	public void createDestAudio() throws IOException {
		// 创建音频文件,合并的文件放这里
		if (!mDestFile.exists()) {
			mDestFile.createNewFile();
		}

		FileOutputStream fileOutputStream = null;
		fileOutputStream = new FileOutputStream(mDestFile);

		// list里面为暂停录音 所产生的 几段录音文件的名字，中间几段文件的减去前面的6个字节头文件
		for (int i = 0; i < mTempFiles.size(); i++) {
			File file = new File(mTempFiles.get(i));
			Log.d(TAG, "录音临时文件的个数 === " + mTempFiles.size());
			FileInputStream fileInputStream = new FileInputStream(file);
			byte[] fileByte = new byte[fileInputStream.available()];
			// 文件长度
			int length = fileByte.length;
			// 头文件
			if (i == 0) {
				while (fileInputStream.read(fileByte) != -1) {
					fileOutputStream.write(fileByte, 0, length);
				}
			} else {// 之后的文件，去掉头文件就可以了
				while (fileInputStream.read(fileByte) != -1) {
					fileOutputStream.write(fileByte, 6, length - 6);
				}
			}

			fileOutputStream.flush();
			fileInputStream.close();

		}
		// 结束后关闭流
		try {
			fileOutputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}


	/**
	 * 删除录音临时文件
	 * 
	 */
	private void deleteTempFiles() {
		for (int i = 0; i < mTempFiles.size(); i++) {
			File file = new File(mTempFiles.get(i));
			if (file.exists()) {
				file.delete();
			}
		}
	}


	private void stopMediaRecorder() {
		if (mMediaRecorder != null) {
			// 停止录音
			mMediaRecorder.stop();
			mMediaRecorder.release();
			mMediaRecorder = null;
		}

	}


	private String getRandomFileName() {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.CHINA);
		return mDestFile.getParent()+"/"+"temp_"+formatter.format(new Date()) + SUFFIX_AAC;
	}
	
	
	

}
